<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <input type="file" id="upload" />
    <div>已上传进度：<span id="progress"></span></div>
    <div>
      <button id="pause">暂停上传</button>
    </div>

    <script>
      const GlobalPerSize = 0.5 * 1024 * 1024;
      let requestList = [];
      // 断点续传顾名思义即断点 + 续传，所以我们第一步先实现“断点”，也就是暂停上传, 利用xhr的abort方法
      // 我们需要将上传每个切片的 xhr 对象保存起来， requestList
      function request({
        url,
        method = 'POST',
        data,
        headers = {},
        onProgress = (e) => e,
        requestList,
      }) {
        return new Promise((resolve, reject) => {
          const xhr = new XMLHttpRequest();
          xhr.upload.onprogress = onProgress;
          xhr.open(method, url);
          Object.keys(headers).map((key) => {
            xhr.setRequestHeader(key, headers[key]);
          });
          xhr.send(data);
          xhr.onload = (e) => {
            // 将请求成的xhr从requestList里面删除
            if (requestList) {
              console.log('请求成功：', xhr);
              // requestList.filter(item=> item === xhr)
              // const xhrIndex = requestList.findIndex(item => item === xhr)
              // requestList.spilce(xhrIndex,1)
            }
            resolve({ data: e.target.response });
          };
          // 每次请求开始，将xhr放入数组内
          requestList?.push(xhr);
          console.log('123: ', requestList);
        });
      }

      const progressDom = document.getElementById('progress');

      let uploadChunkSize = 0;
      const progressHandler = (chunkItem, originFile) => {
        return (e) => {
          uploadChunkSize += e.loaded;
          let percent = uploadChunkSize / originFile.size;
          if (percent > 1) {
            percent = 1;
          }
          progressDom.innerText = percent * 100 + '%';
        };
      };

      document.getElementById('pause').addEventListener('click', () => {
        requestList.forEach((xhr) => xhr?.abort());
        requestList = [];
      });

      document.getElementById('upload').addEventListener('change', async (e) => {
        e.preventDefault();
        const originFile = e.target.files[0];
        const fileName = originFile.name.split('.')[0];

        let currentSize = 0;
        const perSize = GlobalPerSize;
        const fileChunkList = [];
        while (currentSize < originFile.size) {
          fileChunkList.push({ file: originFile.slice(currentSize, currentSize + perSize) });
          currentSize += perSize;
        }

        // 3. 将所有的参数数组转换为请求promise数组
        const requestChunkList = fileChunkList
          .map(({ file }, index) => {
            const formData = new FormData();
            formData.append('chunk', file);
            formData.append('fileName', `${fileName}-${index}`);
            return { formData, index };
          })
          .map(({ formData, index }) =>
            request({
              url: 'http://localhost:3000/',
              data: formData,
              onProgress: progressHandler(fileChunkList[index], originFile),
              requestList,
            })
          );

        const results = await Promise.allSettled(requestChunkList);
        const successfulPromises = results.filter((p) => p.status === 'fulfilled');
        const failedPromises = results.filter((p) => p.status === 'rejected');

        if (failedPromises.length === 0) {
          const mergeRes = await request({
            url: `http://localhost:3000/merge?filename=${originFile.name}&perSize=${GlobalPerSize}`,
          });
          console.log(1, mergeRes);
        }
      });
    </script>
  </body>
</html>
